package dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.transform.AliasToEntityMapResultTransformer;

import bean.Customer;
import bean.UserBean;
import businessBean.FundWithPositionBean;

public class CustomerDAO extends DAO<UserBean> {
	
	public CustomerDAO(SessionFactory factory) {
		super(factory);
	}
	
	public long getCustomerCash(String id)
	{
		return getCustomerById(id).getCash();
	}
	
	public Customer getCustomerById(String id){
		//String idString = String.valueOf(id);
	
		List customers = this.getByAttribute("id", id, Customer.class);
		if(customers != null && customers.size()>0)
		{
			Customer customer = (Customer)customers.get(0);
			return customer;
		}
		return null;
	}
	
	public Customer getCustomerByUsername(String username){
		List customers = this.getByAttribute("username", username, Customer.class);
		if(customers != null && customers.size()>0)
		{
			Customer customer = (Customer)customers.get(0);
			if(customer.getUsername().equals(username))
				return customer;
		}
		return null;
	}
	
	
	public ArrayList<String> createCustomer(Customer c) {
		ArrayList<String> errors = new ArrayList<String>();
		Transaction tx = null;
		Session session = null;
		try {				
			session = this.getSession();
			tx = session.beginTransaction();
			session.saveOrUpdate(c);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)	tx.rollback();
			e.printStackTrace();
			errors.add(e.getMessage());
			return errors;
		} finally {
			if(session != null)	session.close();
		}
		return errors;
	}
	
	public Customer lookUpByUsername(String name) {	
		List<Customer> list = this.getByAttribute("username", name, Customer.class);
		if (list != null && list.size() > 0) {
			Customer customer = list.get(0);
			if(customer.getUsername().equals(name))
				return customer;
		}
		return null;
	}
	
	public List<FundWithPositionBean> lookupPositions(int customerId)
	{
		List<FundWithPositionBean> list = new ArrayList<FundWithPositionBean>();
		StringBuilder sb = new StringBuilder();
		sb.append("select priceDate,Fund.name,shares,price,id from Fund join Position join FundPriceHistory ");
		sb.append("where Fund.id=Position.fundId and FundPriceHistory.fundId=Fund.id and customerId=");
		sb.append(customerId);
		sb.append(';');
		Session session = null;
		Transaction tx = null;
		session = this.getSession();
		tx = session.beginTransaction();
		Query qr = session.createSQLQuery(sb.toString());
		qr.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
		List<Map<String,Object>> aliasToValueMapList=qr.list();
		HashMap<Integer,FundWithPositionBean> beanMap = new HashMap<Integer,FundWithPositionBean>();
		for(Map<String,Object> map:aliasToValueMapList)
		{
			FundWithPositionBean info = new FundWithPositionBean();
			info.setId(Integer.valueOf(map.get("id").toString()));
			info.setName(map.get("name").toString());
			info.setShares(Long.valueOf(map.get("shares").toString()));
			info.setPrice(Long.valueOf(map.get("price").toString()));
			info.setPriceDate(util.Util.convertToDate(map.get("priceDate").toString()));
			info.setValue(util.Util.showValue(info.getShares(),info.getPrice()));
			if(!beanMap.containsKey(info.getId()))
			{
				beanMap.put(info.getId(), info);
			}
			else
			{
				if(info.getPriceDate().compareTo(beanMap.get(info.getId()).getPriceDate())>0)
				{
					beanMap.put(info.getId(),info);
				}
			}
		}
		for(FundWithPositionBean bean:beanMap.values())
		{
			list.add(bean);
		}
		tx.commit();
		session.close();
		return list;		
	}
	// Increase the cash if the amount is larger than 0. Decrease the cash if the amount is less than 0.
	public boolean changeAmount(Customer c, long amount) {
		Transaction tx = null;
		Session session = null;
		try {				
			session = this.getSession();
			tx = session.beginTransaction();			
			c.setCash(c.getCash() + amount);
			session.update(c);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
			return false;
		} finally {
			if(session != null)	session.close();
		}
		return true;
	}
}
